
# 选择排序  时: O(n^2) 空: O(1)  思路：从第i=0个到最后一个元素中选出一个最小的放i处，i++
# 冒泡排序  时: O(n^2) 空: O(1)  思路：从尾部开始排好，不断从前开始比较相邻元素，大的往后冒
# 插入排序  时: O(n^2) 空: O(1)  思路：从前开始排，对于前i-1个数已经有序的情况下，从第i个数往前插
# 希尔排序  时: O(n log n)~O(n^2) 空: O(1)  思路：插入排序的改进，按 gap 分组插入排，逐步缩小 gap
# 归并排序  时: O(n log n) 空: O(n)  思路：递归分组 + 合并排序，每次合并两个有序子数组
# 快速排序  时: O(n log n) 空: O(log n)  思路：选一个基准，把数组分为左右两部分分别递归排序
# 堆排序    时: O(n log n) 空: O(1)  思路：利用最大堆结构，每次取堆顶（最大）元素放末尾
# 计数排序  时: O(n+k) 空: O(k)  思路：统计每个元素出现次数，用数组存储，适用于整数且范围不大
# 桶排序    时: O(n+k) 空: O(n+k)  思路：将数据分到若干“桶”中分别排序再合并，适用于均匀分布
# 基数排序  时: O(nk) 空: O(n+k)  思路：按个位、十位...逐位排序，适用于非比较整数排序
# 杨辉三角 思路：初始化第一层，之后的每层穿插在两个1之间
########################################################################################################################################
#选择排序
def SelectionSort(a):
    n = len(a)
    for i in range(n-1):#此循环保证前i个数据都是排好的
        min = i
        for j in range(i+1,n):
            if a[j] < a[min]:
                min = j
        a[i],a[min] = a[min],a[i]
        print(a)
a = [8,5,2,8,4,1,9]
SelectionSort(a) 
############################################################################################################################################
#冒泡排序
def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        for j in range(0, n - 1 - i):  # 每一轮把最大值“冒”到后面
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
        print(arr)  # 打印每一轮的排序过程

# 示例
a = [8, 5, 2, 8, 4, 1, 9]
bubble_sort(a)
##############################################################################################################################################
#插入排序
def insertion_sort(arr):
    n = len(arr)
    for i in range(1, n):
        key = arr[i]         # 记录当前要插入的值
        j = i - 1
        # 从已排序部分向前比较，找到插入位置
        while j >= 0 and arr[j] > key:
            arr[j + 1] = arr[j]  # 所有比key大的元素右移
            j -= 1
        arr[j + 1] = key         # 插入key到正确位置
        print(arr)  # 打印每一轮的排序结果

# 示例
a = [8, 5, 2, 8, 4, 1, 9]
insertion_sort(a)
#############################################################################################################################################
#希尔排序
def shell_sort(arr):
    n = len(arr)
    gap = n // 2  # 初始gap为数组长度的一半
    while gap > 0:
        for i in range(gap, n):
            temp = arr[i]
            j = i
            # 按gap间隔插入排序
            while j >= gap and arr[j - gap] > temp:
                arr[j] = arr[j - gap]
                j -= gap
            arr[j] = temp
        print(f"gap={gap}:", arr)  # 打印每轮gap下的排序结果
        gap //= 2  # 缩小gap

# 示例
a = [8, 5, 2, 8, 4, 1, 9]
shell_sort(a)
##############################################################################################################################################
#归并排序
def merge_sort(arr):
    if len(arr) <= 1:
        return arr  # 基本情况：单元素数组直接返回

    mid = len(arr) // 2
    left = merge_sort(arr[:mid])     # 递归排序左半部分
    right = merge_sort(arr[mid:])    # 递归排序右半部分

    return merge(left, right)        # 合并两个有序数组 

def merge(left, right): 
    result = []
    i = j = 0
    # 归并两个有序数组
    while i < len(left) and j < len(right):
        if left[i] <= right[j]:  # 保证稳定性：小的或相等的先加入
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    # 把剩余的元素加入
    result.extend(left[i:])
    result.extend(right[j:])
    return result

# 示例
a = [8, 5, 2, 8, 4, 1, 9]
sorted_a = merge_sort(a)
print(sorted_a)
############################################################################################################################################
#快速排序
def quick_sort(arr):
    if len(arr) <= 1:
        return arr  # 基本情况：空或单个元素直接返回

    pivot = arr[0]  # 选取第一个元素作为基准
    less = [x for x in arr[1:] if x <= pivot]   # 所有小于等于pivot的元素
    greater = [x for x in arr[1:] if x > pivot] # 所有大于pivot的元素

    # 递归排序后拼接
    return quick_sort(less) + [pivot] + quick_sort(greater)

# 示例
a = [8, 5, 2, 8, 4, 1, 9]
sorted_a = quick_sort(a)
print(sorted_a)
####################################################################################################################
#堆排序
# 辅助函数：构建最大堆
def heapify(arr, n, i):
    largest = i        # 初始化最大元素为根节点
    left = 2 * i + 1   # 左子节点索引
    right = 2 * i + 2  # 右子节点索引

    # 如果左子节点比根节点大
    if left < n and arr[left] > arr[largest]:
        largest = left

    # 如果右子节点比目前最大还大
    if right < n and arr[right] > arr[largest]:
        largest = right

    # 如果最大值不是根节点，则交换并递归调整
    if largest != i:
        arr[i], arr[largest] = arr[largest], arr[i]
        heapify(arr, n, largest)

# 主函数
def heap_sort(arr):
    n = len(arr)

    # 建堆（从最后一个非叶子节点开始调整）
    for i in range(n // 2 - 1, -1, -1):
        heapify(arr, n, i)

    # 取出最大值（堆顶），放到末尾，然后重新heapify
    for i in range(n - 1, 0, -1):
        arr[0], arr[i] = arr[i], arr[0]  # 把堆顶放到数组最后
        heapify(arr, i, 0)               # 重新调整剩下的堆

    print(arr)

# 示例
a = [8, 5, 2, 8, 4, 1, 9]
#################################################################################################################
heap_sort(a)
#计数排序
def counting_sort(arr):
    if not arr:
        return arr

    max_val = max(arr)
    min_val = min(arr)
    range_val = max_val - min_val + 1

    count = [0] * range_val  # 创建计数数组
    output = [0] * len(arr)  # 输出数组

    # 统计每个元素出现的次数
    for num in arr:
        count[num - min_val] += 1

    # 前缀和，计算每个元素的最终位置
    for i in range(1, range_val):
        count[i] += count[i - 1]

    # 逆序遍历，确保稳定性
    for num in reversed(arr):
        count[num - min_val] -= 1
        output[count[num - min_val]] = num

    print(output)

# 示例
a = [8, 5, 2, 8, 4, 1, 9]
counting_sort(a)
#######################################################################################################################
#桶排序
def bucket_sort(arr):
    if not arr:
        return arr

    n = len(arr)
    buckets = [[] for _ in range(n)]  # 创建n个桶（空列表）

    # 将元素放入对应的桶中
    for num in arr:
        index = int(num * n)  # 映射到桶索引
        buckets[index].append(num)

    # 每个桶内分别排序
    for bucket in buckets:
        bucket.sort()

    # 合并所有桶
    result = []
    for bucket in buckets:
        result.extend(bucket)

    print(result)

# 示例（注意：桶排序适用于浮点数）
a = [0.78, 0.17, 0.39, 0.26, 0.72, 0.94, 0.21]
bucket_sort(a)
####################################################################################################################
#基数排序
def radix_sort(arr):
    if not arr:
        return arr

    max_num = max(arr)
    exp = 1  # 表示当前处理的数位（1, 10, 100, ...）

    while max_num // exp > 0:
        counting_sort_by_digit(arr, exp)
        exp *= 10

    print(arr)

# 对某个位数进行计数排序（辅助函数）
def counting_sort_by_digit(arr, exp):
    n = len(arr)
    output = [0] * n
    count = [0] * 10  # 十进制中数字的范围是 0~9

    # 统计该位出现次数
    for num in arr:
        index = (num // exp) % 10
        count[index] += 1

    # 转换成前缀和（确定位置）
    for i in range(1, 10):
        count[i] += count[i - 1]

    # 从后向前填充输出数组（保持稳定性）
    for i in range(n - 1, -1, -1):
        index = (arr[i] // exp) % 10
        count[index] -= 1
        output[count[index]] = arr[i]

    # 将输出复制回原数组
    for i in range(n):
        arr[i] = output[i]

# 示例
a = [170, 45, 75, 90, 802, 24, 2, 66]
radix_sort(a)
######################################################################################################################################
# #杨辉三角
def ge(n):
    if n <= 0:
        return []
    # 初始化结果列表，第一行总是[1]
    triangle = [[1]]
    for i in range(1, n):
        # 上一行
        prev_row = triangle[i-1]
        # 当前行，开始和结束都是1
        current_row = [1]
        # 计算中间元素
        for j in range(1, i):
            current_row.append(prev_row[j-1] + prev_row[j])
        # 添加行尾的1
        current_row.append(1)
        # 将当前行添加到结果中
        triangle.append(current_row)
    return triangle
n = 5
pascal = ge(n)
print(pascal)
###################################################################################################################################################